// Copyright 2022 Huawei Cloud Computing Technology Co., Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "CaeHttpsJobThread.h"
#include "../cae_agent/CaeAgent.h"
#include "../cae_common/CaeMsgCode.h"
#include "CaeParamStorage.h"

CaeHttpsJobThread::CaeHttpsJobThread()
{
    pthread_mutex_init(&m_jobsLock, nullptr);
    m_currentJobId = 0;
}

CaeHttpsJobThread::~CaeHttpsJobThread()
{
    pthread_mutex_destroy(&m_jobsLock);
}

void CaeHttpsJobThread::Run()
{
    char threadName[] = "HttpsJobThread";
    prctl(PR_SET_NAME, threadName);
    while (m_threadStatus == CAE_THREAD_STATUS_RUNNING) {
        if (m_jobs.empty()) {
            usleep(100000);
            continue;
        }
        LOGD("m_jobs size: %d", m_jobs.size());
        HttpsJobInfo *httpsJobInfoTemp = m_jobs.front();
        uint16_t jobType = httpsJobInfoTemp->GetJobType();
        switch (jobType) {
            case HttpsJobType::NOTIFY_START: {
                if (!CaeHttpsJob::GetInstance().StartNotify()) {
                    LOGE("Send notify_Start job failed.");
                    if (!(CaeClientNotifyTool::GetInstance().SendMsgToClient(CAE_VERIFY_SESSION_ID_INVALID))) {
                        LOGE("Send CAE_VERIFY_SESSION_ID_INVALID error");
                    }
                    CaeAgent::GetInstance().CloseClient();
                } else {
                    LOGI("Send notify_Start job success.");
                }
                CaeHttpsJob::GetInstance().InitResponseMem(NOTIFY_START);
                break;
            }
            case HttpsJobType::NOTIFY_STOP: {
                if (!CaeHttpsJob::GetInstance().StopNotify()) {
                    LOGE("Send notify_Stop job failed.");
                } else {
                    LOGI("Send notify_Stop job success.");
                }
                CaeParamStorage::GetInstance().ClearAllParams();
                CaeHttpsJob::GetInstance().InitResponseMem(NOTIFY_STOP);
                break;
            }
            case HttpsJobType::QUERY_AES_KEY: {
                if (!CaeHttpsJob::GetInstance().QueryAESKey()) {
                    LOGE("Send query_AesKey job failed.");
                } else {
                    LOGI("Send query_AesKey job success.");
                }
                break;
            }
            case HttpsJobType::NOTIFY_HEARTBEAT: {
                if (!CaeHttpsJob::GetInstance().HeartbeatNotify()) {
                    LOGE("Send HeartbeatNotify job failed.");
                    if (CaeAgent::GetInstance().IsUserConnected()) {
                        if (!(CaeClientNotifyTool::GetInstance().SendMsgToClient(CAE_VERIFY_SESSION_ID_INVALID))) {
                            LOGE("Send CAE_VERIFY_SESSION_ID_INVALID error");
                        }
                        CaeAgent::GetInstance().CloseClient();
                    }
                }
                CaeHttpsJob::GetInstance().InitResponseMem(NOTIFY_HEARTBEAT);
                break;
            }
            default:
                break;
        }
        m_jobs.pop();
    }
    m_threadStatus = CAE_THREAD_STATUS_STOP;
    while (!m_jobs.empty()) {
        HttpsJobInfo *httpsJobInfoTemp = m_jobs.front();
        m_jobs.pop();
        delete httpsJobInfoTemp;
    }
}

int CaeHttpsJobThread::AddHttpsJob(HttpsJobType httpsJobType)
{
    pthread_mutex_lock(&m_jobsLock);
    LOGD("m_currentJobId: %d", m_currentJobId);
    HttpsJobInfo *jobInfo = new (std::nothrow) HttpsJobInfo();
    if (jobInfo == nullptr) {
        LOGE("Create job info failed.");
        return -1;
    }
    jobInfo->SetJobType(httpsJobType);
    this->m_jobs.push(jobInfo);
    m_currentJobId++;
    m_currentJobId = m_currentJobId % 100;
    jobInfo->SetJobId(m_currentJobId);
    pthread_mutex_unlock(&m_jobsLock);
    return 0;
}

uint16_t CaeHttpsJobThread::GetCurrentJobId()
{
    return this->m_currentJobId;
};